home *** CD-ROM | disk | FTP | other *** search
/ Pascal Super Library / Pascal Super Library (CW International)(1997).bin / LIBRARY / CMPLTPAS / GAMER.ASM < prev    next >
Assembly Source File  |  1988-08-01  |  11KB  |  275 lines

  1. ;===========================================================================
  2. ;
  3. ;    G A M E R  -  Assembly language joystick support for Turbo Pascal
  4. ;
  5. ;===========================================================================
  6. ;
  7. ;    by Jeff Duntemann     12 February 1988
  8. ;      with thanks to Ted Mirecki for additional insights
  9. ;
  10. ;     From: COMPLETE TURBO PASCAL 5.0  by Jeff Duntemann
  11. ;    Scott, Foresman & Co., Inc. 1988   ISBN 0-673-38355-5
  12. ;
  13. ;
  14. ; GAMER is a single assembly-language source file that contains both
  15. ; STICK.ASM and BUTTON.ASM, which are given separately elsewhere in
  16. ; COMPLETE TURBO PASCAL, 3E.  The purpose of GAMER is to show how multiple
  17. ; assembly language procedures may be combined into a single machine-code
  18. ; module to lessen program clutter.
  19. ;
  20. ; The idea is to create a Turbo Pascal unit incorporating the routines in
  21. ; this module.  The unit source file is GAMEBORD.PAS.  The headers of both
  22. ; routines must be laid out in the interface section of GAMEBORD.PAS, and
  23. ; the .OBJ file containing the routines must be loaded into the
  24. ; implementation section of GAMEBORD.PAS using the $L compiler directive:
  25. ;
  26. ; INTERFACE
  27. ;
  28. ; FUNCTION  Button(StickNumber,ButtonNumber : Integer) : Boolean;
  29. ;
  30. ; PROCEDURE Stick(StickNumber : Integer;
  31. ;               VAR X       : INTEGER;
  32. ;               VAR Y       : INTEGER);
  33. ;
  34. ; IMPLEMENTATION
  35. ;
  36. ; {$L GAMER}
  37. ; FUNCTION Button; EXTERNAL;
  38. ; PROCEDURE Stick; EXTERNAL;
  39. ;
  40. ;
  41. ;
  42. ; GAMEBORD.PAS is given elsewhere in COMPLETE TURBO PASCAL, 3E
  43. ;
  44. ;
  45. ; To reassemble/relink GAMER:
  46. ;-------------------------------------
  47. ; Assemble this file with MASM.  "C>MASM GAMER;"
  48. ;
  49. ;
  50.  
  51.  
  52. CODE    SEGMENT BYTE PUBLIC      ; THE SEGMENT IS BYTE-ALIGNED
  53.         ASSUME CS:CODE
  54.         PUBLIC BUTTON,STICK      ; THE TWO ACCESSIBLE PROCS IN THIS MODULE
  55.  
  56.  
  57.  
  58. ;===========================================================================
  59. ;    B U T T O N  -  Function to return the state of the joystick buttons
  60. ;===========================================================================
  61. ;
  62. ; The full function header follows:
  63. ;
  64. ; FUNCTION BUTTON(StickNumber,ButtonNumber : Integer) : Boolean;
  65. ;
  66. ; StickNumber specifies which joystick to read from, and ButtonNumber
  67. ; specifies which of the two buttons on that joystick to read.  If the
  68. ; specified button is down, BUTTON returns a Boolean value of TRUE.
  69. ;
  70. ; Yes, this is the long way 'round; assembly language is in no way required
  71. ; to read four bits from an ordinary 8088 I/O port.  BUTTON exists only as
  72. ; practice in creating assembly language external functions.
  73. ;
  74. ; The button information is obtained by reading I/O port $201.  The high
  75. ; four bits represent the state of the four buttons (two for each of the
  76. ; two possible joysticks) at the instant the port is read.  A LOW bit
  77. ; represents a button DOWN.  This is why the byte read from the port is
  78. ; inverted via NOT before the selected bit is tested.
  79. ;
  80. ; Here is a map of the button bits as returned by port $201:
  81. ;
  82. ;     |7 6 5 4 3 2 1 0|
  83. ;      | | | |
  84. ;      | | |  - - - - - - -> Button #1, joystick #1
  85. ;      | |  - - - - - - - -> Button #2, joystick #1
  86. ;      |  - - - - - - - - -> Button #1, joystick #2
  87. ;       - - - - - - - - - -> Button #2, joystick #2
  88. ;
  89. ; Remember that the return value from this function is passed to the runtime
  90. ; code in the AL register.
  91. ;
  92. ;
  93. ; This structure defines the layout of BUTTON's parameters on the stack:
  94. ;
  95. ONSTACK1  STRUC
  96. OLDBP     DW   ?                ;TOP OF STACK
  97. RETADDR   DD   ?                ;FAR RETURN ADDRESS
  98. BTN_NO    DW   ?                ;BUTTON NUMBER
  99. STIK_NO   DW   ?                ;STICK NUMBER
  100. ONSTACK1  ENDS
  101.  
  102. BUTTON  PROC    FAR             ;ALL PROCS IN A UNIT ARE FAR PROCS
  103.         PUSH    BP              ;SAVE PREVIOUS VALUE OF BP ON STACK
  104.         MOV     BP,SP           ;SP BECOMES NEW VALUE OF BP
  105.  
  106. ;-------------------------------------------------------------------
  107. ; THE BULK OF THIS ROUTINE SETS UP A TEST MASK BY WHICH ONE SINGLE
  108. ; BIT OUT OF THE FOUR BUTTON BITS IS TESTED.
  109. ;-------------------------------------------------------------------
  110.  
  111.         MOV     BL,010H         ;START WITH HIGH BIT IN BIT 4
  112.         CMP     [BP].STIK_NO,2  ;ARE WE TESTING FOR JOYSTICK #2?
  113.         JNE     WHICH           ;IF NOT, GO ON TO TEST FOR WHICH BUTTON,
  114.         SHL     BL,1            ; OTHERWISE SHIFT TWO POSITIONS LEFTWARD
  115.         SHL     BL,1            ; SO THAT THE MASK IS ON BIT 6 FOR STICK 2
  116.  
  117. WHICH:  CMP     [BP].BTN_NO,2   ;ARE WE TESTING FOR BUTTON #2?
  118.         JNE     READEM          ;IF NOT, MASK IS CORRECT; GO READ PORT
  119.         SHL     BL,1            ;OTHERWISE, SHIFT 1 BIT LEFT FOR BUTTON 2
  120.  
  121. ;------------------------------------------------------------------------
  122. ; THE BIT MASK IS NOW CORRECT.  HERE THE BUTTON BITS ARE READ FROM PORT
  123. ; $201 AND TESTED AGAINST THE MASK.  NOTE THAT THE BITS AS READ FROM
  124. ; THE PORT MUST BE INVERTED SO THAT THE Z FLAG IS SET RATHER THAN CLEARED
  125. ; ON AN ACTIVE BUTTON BIT.  (BITS ARE ACTIVE **LOW**, REMEMBER!)
  126. ;------------------------------------------------------------------------
  127.  
  128. READEM: MOV     DX,0201H        ;SET UP 16-BIT ADDRESS FOR PORT READ
  129.         IN      AL,DX           ;READ BUTTON BITS FROM PORT $201
  130.         NOT     AL              ;MUST INVERT BITS FOR PROPER SENSE
  131.                                 ; OF THE Z FLAG AFTER TESTING
  132.         TEST    AL,BL           ;SEE IF THE DESIRED BIT IS HIGH;
  133.         JNZ     PUSHED          ;IF SO, BUTTON IS PUSHED,
  134.         MOV     AL,0            ;SO MOVE BOOLEAN FALSE INTO AL
  135.         JMP     BDONE           ;AND GET OUT OF HERE
  136.  
  137. PUSHED: MOV     AL,1            ;BUTTON DOWN; MOVE BOOLEAN TRUE INTO AL
  138.  
  139. BDONE:  MOV     SP,BP           ;RESTORE PRIOR STACK POINTER & BP
  140.         POP     BP              ; IN CONVENTIONAL RETURN
  141.         RET     6
  142.  
  143. BUTTON  ENDP
  144.  
  145.  
  146.  
  147. ;===========================================================================
  148. ;    S T I C K  -  Procedure to read either joystick
  149. ;===========================================================================
  150. ;
  151. ; The procedure header follows:
  152. ;
  153. ;    PROCEDURE STICK(StickNumber : Integer VAR X,Y : Integer);
  154. ;
  155. ; StickNumber specifies which joystick to read from, and the X and Y
  156. ; parameters return integers proportional to the joystick's position
  157. ; at the moment the stick is sampled.  These integers will vary from
  158. ; stick to stick depending on the resistance of the potentiometers
  159. ; used within the stick, but will typically from from 3 to 150.
  160. ;
  161. ; The IBM standard game controller board consists of two pairs of
  162. ; one-shots, which output a pulse when triggered by an I/O write to
  163. ; I/O port $201.  The length of this pulse is determined by an RC
  164. ; time constant circuit the resistance portion of which is the
  165. ; potentiometer in the joystick.  As the handle is moved around, the
  166. ; two potentiometers (one for X, one for Y) run up and back, changing
  167. ; resistance as they go.
  168. ;
  169. ; To read one of the two joysticks, a dummy value (which may be anything
  170. ; at all) is written to I/O port $201.  Port $201 must then be polled
  171. ; continuously, incrementing a register at each polling event.  When
  172. ; the bit corresponding to that stick's X or Y coordinate changes state,
  173. ; the count in the register is returned as that coordinate value at the
  174. ; time the stick was sampled.
  175. ;
  176. ; Here is a map of the joystick bits as returned by port $201:
  177. ;
  178. ;     |7 6 5 4 3 2 1 0|
  179. ;              | | | |
  180. ;              | | | - - - - - - -> X coordinate, joystick #1
  181. ;              | | - - - - - - - -> Y coordinate, joystick #1
  182. ;              | - - - - - - - - -> X coordinate, joystick #2
  183. ;              - - - - - - - - - -> Y coordinate, joystick #2
  184. ;
  185. ; One thing to keep in mind is that a bit goes LOW when sampled, and
  186. ; you must test for a HIGH on that bit to indicate that the one-shot has
  187. ; timed out.
  188. ;
  189. ;
  190. ;
  191. ; This structure defines STICK's parameters on the stack.
  192. ;
  193. ONSTACK2  STRUC
  194. OLDBP2    DW   ?               ;TOP OF STACK
  195. RETADDR2  DD   ?               ;FAR RETURN ADDRESS
  196. YADDR2    DD   ?               ;FAR ADDRESS OF X VALUE
  197. XADDR2    DD   ?               ;FAR ADDRESS OF Y VALUE
  198. STIK_NO2  DW   ?               ;STICK NUMBER
  199. ONSTACK2  ENDS
  200.  
  201. ;  EQUATES FOR ONE-SHOT BITS FOR STICKS 1 & 2
  202.  
  203. STICK_X   EQU      1
  204. STICK_Y   EQU      2
  205.  
  206.  
  207. STICK     PROC    FAR
  208.           PUSH    BP          ;SAVE CALLER'S BP
  209.           MOV     BP,SP       ;STACK POINTER BECOMES NEW BP
  210.           PUSH    DS
  211.  
  212. ;  GET THE X AXIS VALUE FIRST
  213.  
  214.           MOV     AH,STICK_X       ; MOVE IN THE X TEST BIT
  215.           CMP     [BP].STIK_NO2,2  ; SEE IF WE'RE TESTING STICK #1 OR #2
  216.           JNE     TEST_X
  217.           SHL     AH,1        ; SHIFT BIT NUMBERS 2 LEFT FOR STICK #2
  218.           SHL     AH,1
  219. TEST_X:   MOV     AL,1        ; INITIALIZE OUTPUT VALUE
  220.           MOV     DX,201H     ; SET PORT ADDRESS
  221.           MOV     BX,0        ; AND KEEPING THE RUNUP COUNT IN BX
  222.           MOV     CX,BX       ; LOOP 64K TIMES MAX
  223.           OUT     DX,AL       ; TRIGGER THE ONE-SHOTS
  224. AGAIN_X:  IN      AL,DX       ; READ THE ONE-SHOT BITS
  225.           TEST    AL,AH       ; TEST FOR A HIGH BIT 0
  226.           JE      DELAY       ; WE'RE DONE IF BIT 0 IS HIGH
  227.           INC     BX          ; OTHERWISE INCREMENT BX AND LOOP AGAIN
  228.           LOOP    AGAIN_X
  229.           MOV     BX,-1       ; SET X=-1 IF NO RESPONSE
  230.  
  231. ;  DELAY HERE TO LET THE OTHER THREE PULSES MAX OUT
  232.  
  233. DELAY:    MOV     CX,512
  234. WAIT:     LOOP    WAIT
  235.  
  236. ;  NOW WE GET THE Y AXIS VALUE
  237.  
  238.           MOV     AH,STICK_Y       ; MOVE IN THE Y TEST BIT
  239.           CMP     [BP].STIK_NO2,2  ; SEE IF WE'RE TESTING STICK #1 OR #2
  240.           JNE     TEST_Y
  241.           SHL     AH,1        ; SHIFT BIT NUMBERS 2 LEFT FOR STICK #2
  242.           SHL     AH,1
  243.  
  244. TEST_Y:   MOV     SI,0        ; KEEP THE RUNUP COUNT FOR Y IN SI
  245.           MOV     CX,SI       ; SET LOOP LIMIT TO 64K
  246.           OUT     DX,AL       ; FIRE THE ONE-SHOTS AGAIN
  247. AGAIN_Y:  IN      AL,DX       ; READ THE ONE-SHOT BITS
  248.           TEST    AL,AH       ; TEST FOR A HIGH BIT 1
  249.           JE      DONE        ; WE'RE DONE IF BIT 1 IS HIGH
  250.           INC     SI          ; OTHERWISE INCREMENT SI AND LOOP AGAIN
  251.           LOOP    AGAIN_Y
  252.           MOV     SI,-1       ; SET Y=-1 IF NO RESPONSE
  253.  
  254. ;  MOVE RETURN VALUES FROM REGISTERS INTO VAR PARAMETERS X & Y
  255.  
  256. DONE:     LDS     DI,[BP].XADDR2         ;ADDR OF X INTO DS:DI
  257.           MOV     [DI],BX                ;X VALUE FROM BX TO DS:DI
  258.           LDS     DI,[BP].YADDR2         ;DITTO FOR Y VALUE FROM SI
  259.           MOV     [DI],SI
  260.  
  261. ;  IT'S OVER...NOW CLEAN UP THE STACK AND LEAVE
  262.  
  263.           POP     DS
  264.           MOV     SP,BP                ; CLEAN UP STACK AND LEAVE
  265.           POP     BP                   ; RESTORE CALLER'S BP
  266.  
  267.           RET     10
  268.  
  269. STICK     ENDP
  270.  
  271.  
  272.  
  273. CODE      ENDS
  274.           END
  275.